/*
 * Copyright (C) 2025 Huawei Device Co., Ltd.
 * Licensed under the Apache License, Version 2.0 (the 'License');
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an 'AS IS' BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#ifndef LOTTIETURBO_NAPI_HELPER_H
#define LOTTIETURBO_NAPI_HELPER_H

#include "dataManager/data_parse.h"
#include "napi/native_api.h"
#include <arkui/native_type.h>
#include <string>

namespace LottieTurbo {

class NapiHelper {
public:
    explicit NapiHelper(napi_env env);

    napi_env GetEnv();

    napi_value GetGlobal();

    ArkUI_NodeContentHandle GetNodeContentHandle(napi_value value);

    napi_value Call(napi_value thisObject, napi_value callback, int argsCount, const napi_value *args);

    napi_value CreateString(std::string const &str);

    napi_value CreateInteger(int32_t const &value);

    napi_value CreateDouble(double const &value);

    napi_value CreateArray(std::vector<napi_value> const &value);

    napi_value CreateBoolean(const bool &value);

    napi_value CreateFunction(std::string const &name, napi_callback callback, void *data = nullptr);

    napi_ref CreateReference(napi_value value);

    napi_value CreateObject();

    std::string GetString(napi_value value);

    double GetDouble(napi_value value);

    int GetInteger(napi_value value);

    bool GetBoolean(napi_value value);
    
    Resource GetResource(napi_value value);

    napi_value GetArrayElement(napi_value array, uint32_t index);

    uint32_t GetArrayLength(napi_value array);

    napi_value GetObjectProperty(napi_value object, std::string const &key);

    napi_value GetObjectProperty(napi_value object, napi_value key);

    napi_value GetReferenceValue(napi_ref ref);

    std::vector<napi_value> GetCallbackArgs(napi_callback_info info);

    std::vector<napi_value> GetCallbackArgs(napi_callback_info info, size_t args_count);

    void DeleteReference(napi_ref reference);

    void addObjectProperty(napi_value object, napi_value key, napi_value value);

    bool CheckFuncIsExist(napi_value jsObject, std::string const &funcName);

    bool CheckIsArray(napi_value jsObject);

    bool CheckPropIsExist(napi_value jsObject, std::string const &propName);

    bool CheckIsType(napi_value value, napi_valuetype type);

    template <typename T> T *UnwrapInstance(napi_value object)
    {
        T *obj = nullptr;
        auto status = napi_unwrap(env_, object, reinterpret_cast<void **>(&obj));
        this->MaybeThrowFromStatus(status, "Failed to unwrap an instance");
        return obj;
    }

    template <typename T> T *UnwrapInstanceFromCallBack(napi_callback_info info)
    {
        napi_value jsThis;
        napi_get_cb_info(env_, info, nullptr, nullptr, &jsThis, nullptr);
        return UnwrapInstance<T>(jsThis);
    }

private:
    napi_env env_;

    void MaybeThrowFromStatus(napi_status status, const char *message);

    void MaybeRethrowAsCpp(napi_status status);
};

} // namespace LottieTurbo
#endif // LOTTIETURBO_NAPI_HELPER_H
